/*
 * PublicLog.cpp
 *
 *  Created on: 2015-6-24
 *      Author: root
 */

#include"PublicLog.h"
#include"PublicTool.h"
#include"PublicThread.h"
#if !USE_PUBLIC_LOG_EX
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdarg.h>
#include<dirent.h>
#ifdef __MINGW32__
#include<windows.h>
#define FATAL_COLOR_CMD		0x06
#define ERROR_COLOR_CMD		0x0C
#define WARNING_COLOR_CMD	0x0E
#define INFO_COLOR_CMD		0x0B
#define DEBUG_COLOR_CMD		0x07
#define FINE_COLOR_CMD		0x07
#define FINEST_COLOR_CMD	0x07
//FOREGROUND_INTENSITY|FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED
#define NORMAL_COLOR_CMD	0x0F
static int colortypecmd[]={
FATAL_COLOR_CMD,ERROR_COLOR_CMD,WARNING_COLOR_CMD,INFO_COLOR_CMD,
DEBUG_COLOR_CMD,FINE_COLOR_CMD,FINEST_COLOR_CMD,NORMAL_COLOR_CMD};
static HANDLE nStdHandle=GetStdHandle(STD_OUTPUT_HANDLE);
#endif
#define FATAL_COLOR		"\033[01;31m"
#define ERROR_COLOR		"\033[22;31m"
#define WARNING_COLOR	"\033[01;33m"
#define INFO_COLOR		"\033[22;36m"
#define DEBUG_COLOR		"\033[01;37m"
#define FINE_COLOR		"\033[22;37m"
#define FINEST_COLOR	"\033[22;37m"
#define NORMAL_COLOR	"\033[0m"
static const char*colortype[]={
FATAL_COLOR,ERROR_COLOR,WARNING_COLOR,INFO_COLOR,
DEBUG_COLOR,FINE_COLOR,FINEST_COLOR,NORMAL_COLOR};

//__asm__(".symver __isoc99_sscanf,sscanf@GLIBC_2.2.5");
//默认6M
//#define MAX_BUFFSIZE 20480
#define MAX_BUFFSIZE	409600
#define SEEK_DATETIME -604800
static FILE*normal_fp=NULL;//普通文件指针
static FILE*error_fp=NULL;//错误文件指针
static FILE*ex_fp=NULL;//扩展信息文件指针

static int  today=0;//当前日期
static char PerFileName[128]={0};//文件名前缀
static int  bInitFile=0;//初始化文件
static PublicLock mutex;
static int  DebugMode=0;
static int  ShowMode=1;
#ifdef USE_CMD_COLOR 
static int  CmdMode=1;
#else
static int  CmdMode=0;
#endif
#define SAFE_CLOSE(x) do{if(x)fclose(x);x=NULL;}while(0)
void WriteLog(int level,const char*DateTime,const char*Buffer);

void SetEnableDebug(int bDebug){
    DebugMode=bDebug;
}
void SetDisableShow(int disShow){
	if(disShow){
		ShowMode=0;
	}else{
		ShowMode=1;
	}
}
void SetCMDMode(int bCmd){
	CmdMode=bCmd;
}
void Log(int level,const char*format,...){
//非debug模式不显示信息
    if(DebugMode==0&&level==_DEBUG_) return;
    mutex.Lock();
    char DateTimeString[32]={0};
    char Buffer[MAX_BUFFSIZE]={0};
    int Size=0;
    va_list arguments;
    va_start(arguments,format);
    Size=vsnprintf(Buffer,MAX_BUFFSIZE-64,format,arguments);
    va_end(arguments);
    if(Size>0){
		GetDateTimeString(DateTimeString,sizeof(DateTimeString));
		if(ShowMode){
#ifdef __MINGW32__
			if(CmdMode){
				SetConsoleTextAttribute(nStdHandle,colortypecmd[level]);
#ifdef USE_CMD_COLOR 
				printf("[%s]%s\n",DateTimeString,Buffer);
#else				
				WCHAR WBuffer[MAX_BUFFSIZE]={0};
				MultiByteToWideChar(CP_UTF8,0,Buffer,-1,WBuffer,MAX_BUFFSIZE);
				WideCharToMultiByte(CP_ACP,0,WBuffer,-1,Buffer,MAX_BUFFSIZE,NULL,NULL);
				printf("[%s]%s\n",DateTimeString,Buffer);
#endif				
				SetConsoleTextAttribute(nStdHandle,colortypecmd[_NORMAL_]);
			}else{
				printf("%s[%s]%s%s\n",colortype[level],DateTimeString,Buffer,colortype[_NORMAL_]);
			}
#else						
			printf("%s[%s][%lu]%s%s\n",colortype[level],DateTimeString,pthread_self(),Buffer,colortype[_NORMAL_]);		
#endif			
		}
		WriteLog(level,DateTimeString,Buffer);
    }
    mutex.UnLock();
}
void OpenLog();
void DelLog();
void CloseLog();
void CheckFile();
void WriteLog(int level,const char*DateTime,const char*Data){
	if(bInitFile==0)return;
	CheckFile();
	char Buffer[MAX_BUFFSIZE]={0};
	int Size=snprintf(Buffer,MAX_BUFFSIZE,"[%s][%lu]%s\n",DateTime,pthread_self(),Data);
	FILE*fp=NULL;
	if(level==_ERROR_){
		fp=error_fp;
	}else
	if(level==_FINE_){
		fp=ex_fp;
	}else{
		fp=normal_fp;
	}
	if(fp){
		fwrite(Buffer,1,Size,fp);
	}
}
#include<sys/stat.h>
FILE*OpenLog(const char*datestr,const char*flag){
	FILE*fp=NULL;
	char FullFileName[128]={0};
	sprintf(FullFileName,"logs/%s_%s.%s.log",PerFileName,datestr,flag);
	fp=fopen(FullFileName,"ab");
	if(fp!=NULL){
//644 确保其它用户有读取权限
		fchmod(fileno(fp),S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
		setbuf(fp,0);
	}else{
		fprintf(stderr,"Open File:%s Failed!!!\n",FullFileName);
	}
	return fp;
}
//打开日志
void OpenLog(){
	char DateString[32]={0};
	GetDateString(DateString,sizeof(DateString));
	normal_fp=OpenLog(DateString,"nor");
	error_fp=OpenLog(DateString,"err");
	ex_fp=OpenLog(DateString,"ex");
	today=GetToDay();
}
void CloseLog(){
	SAFE_CLOSE(normal_fp);
	SAFE_CLOSE(error_fp);
	SAFE_CLOSE(ex_fp);
}
//删除日志
void DelLog(){
	char CheckDateString[32]={0};
	char CheckFileName[128]={0};
	char CheckFileNameRule[128]={0};
	sprintf(CheckFileName,"%s_",PerFileName);//文件名前缀
	sprintf(CheckFileNameRule,"%s_%%[^._]",PerFileName);//检查规则
	GetDateString(CheckDateString,sizeof(CheckDateString),SEEK_DATETIME);//检查日期
	DIR *dir = opendir("logs");
	struct dirent *dirp = NULL;
	if(dir!=NULL){
		while((dirp = readdir(dir))!=NULL){
			//排除非文件类型
#ifndef __MINGW32__             
			UpdateFileType(dirp,"logs");
			if(dirp->d_type!=8){
				continue;
			}
#endif       
			//排除前缀不一致的
			if(strncmp(dirp->d_name,CheckFileName,strlen(CheckFileName))!=0){
				continue;
			}
			char DateString[32]={0};
			//根据规则获取时间
			sscanf(dirp->d_name,CheckFileNameRule,DateString);
			if(strlen(CheckDateString)==strlen(DateString)){
				if(strcmp(CheckDateString,DateString)>0){
					char localfilename[1024]={0};
					sprintf(localfilename,"logs/%s",dirp->d_name);
					unlink(localfilename);
					//unlink(dirp->d_name);
				}
			}
		}
		closedir(dir);
	}
}
//打开日志文件
int OpenPublicLog(const char*perfilename){
	strcpy(PerFileName,perfilename);
	bInitFile=1;
	if(CreateFolder("logs",1)!=0){
		WRONG("创建日志存储目录失败");
		exit(0);
	}
	CheckFile();
	INFO("******日志创建成功******");
	return 0;
}
//关闭日志文件
int ClosePublicLog(){
	INFO("******关闭日志文件******");
	bInitFile=0;
	sleep(1);
	CloseLog();
	return 0;
}
void CheckFile(){
	if(today!=GetToDay()){
		CloseLog();
		DelLog();
		OpenLog();
	}
}
#endif
